package top.jolyoulu.corecommon.utils.other;

import lombok.Data;

import java.util.HashMap;
import java.util.List;
import java.util.Random;
import java.util.concurrent.ThreadLocalRandom;

/**
 * @Author: JolyouLu
 * @Date: 2023/3/18 14:53
 * @Description
 */
public class RandomUtils {

    private RandomUtils() {
        throw new IllegalStateException("Utility class");
    }


    private static final String str = "qwertyuioplkjhgfdsazxcvbnmQAZWSXEDCRFVTGBYHNUJMIKLOP0123456789";

    /**
     * 生成随机字符串
     * @param len 字符串长度
     * @return
     */
    public static String nextStr(int len){
        StringBuilder res = new StringBuilder();
        Random rd = ThreadLocalRandom.current();
        for (int i = 0; i < len; i++) {
            res.append(str.charAt(rd.nextInt(str.length())));
        }
        return res.toString();
    }

    /**
     * 生成随机字符串
     * @param len 字符串长度
     * @param sourceStr 从源字符串中生成
     * @return
     */
    public static String nextStr(int len,String sourceStr){
        StringBuilder res = new StringBuilder();
        Random rd = ThreadLocalRandom.current();
        for (int i = 0; i < len; i++) {
            res.append(sourceStr.charAt(rd.nextInt(sourceStr.length())));
        }
        return res.toString();
    }

    /**
     * 根据权值生成数据
     * @param weights 权值数组
     * @return
     */
    public static <T> T nextByWeight(List<Weight<T>> weights) {
        if (weights.isEmpty()){
            throw new IllegalArgumentException("weights 不能为空");
        }
        //总权值
        int total = 0;
        //权值数组
        int[] w = new int[weights.size()];
        //值数组
        Object[] v = new Object[weights.size()];
        for (int i = 0; i < weights.size(); i++) {
            if (weights.get(i).getWeight() <= 0){
                continue;
            }
            total += weights.get(i).getWeight();
            if (i == 0) {
                w[i] = weights.get(i).getWeight();
            } else {
                w[i] = w[i - 1] + weights.get(i).getWeight();
            }
            v[i] = weights.get(i).getValue();
        }
        ThreadLocalRandom random = ThreadLocalRandom.current();
        if (total == 0){
            return null;
        }
        int nextInt = random.nextInt(total) + 1;
        for (int i = 0; i < w.length; i++) {
            if (nextInt < w[i]) {
                @SuppressWarnings("unchecked")
                T res = (T) v[i];
                return res;
            }
        }
        return null;
    }

    /**
     * 在给定的区间随机生成数据
     * @param low 最小值(包含)
     * @param high 最大值(包含)
     * @return
     */
    public static Integer nextBySection(Integer low,Integer high){
        if (high < low){
            throw new IllegalArgumentException("end 必须大于 start");
        }
        int diff = high - low + 1;
        ThreadLocalRandom random = ThreadLocalRandom.current();
        return low + random.nextInt(diff);
    }

    @Data
    public static class Weight<T> {
        //权值
        private int weight;
        //值
        private T value;

        public Weight(T value, int weight) {
            this.weight = weight;
            this.value = value;
        }
    }

    public static void main(String[] args) {
        //测试权值生成
//        List<Weight> bo = new ArrayList<>();
//        bo.add(new Weight("50%", 50));
//        bo.add(new Weight("30%", 30));
//        bo.add(new Weight("20%", 20));
//        int a = 0;
//        int b = 0;
//        int c = 0;
//        for (int i = 0; i < 100000; i++) {
//            switch (RandomUtil.nextByWeight(bo)) {
//                case "50%":
//                    a++;
//                    break;
//                case "30%":
//                    b++;
//                    break;
//                case "20%":
//                    c++;
//                    break;
//            }
//        }
//        System.out.println("50% 出现次数 => " + a);
//        System.out.println("30% 出现次数 => " + b);
//        System.out.println("20% 出现次数 => " + c);
        //测试从区间随机生成数据
        HashMap<Integer, Integer> map = new HashMap<>();
        for (int i = 0; i < 1000; i++) {
            Integer next = RandomUtils.nextBySection(81, 90);
            if (map.containsKey(next)) {
                map.put(next,map.get(next) + 1);
            }else {
                map.put(next,1);
            }
        }
        System.out.println(map);
    }

}
